package com.ams.io.network;

import java.io.IOException;
import java.net.SocketAddress;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;

import com.ams.io.network.connection.ConnectionListener;
import com.ams.io.network.connection.DatagramConnector;
import com.ams.io.network.connection.IFramerFactory;

public class DatagramAcceptor extends NetworkHandler {
    private SocketAddress listenEndpoint;
    private IFramerFactory framerFactory = null;

    private DatagramChannel datagramChannel;
    private Dispatcher dispatcher;
    private ConnectionListener listener;

    public DatagramAcceptor(SocketAddress listenEndpoint) {
        this.listenEndpoint = listenEndpoint;
    }

    private void openChannel() throws IOException {
        datagramChannel = DatagramChannel.open();
        datagramChannel.socket().bind(listenEndpoint);
        datagramChannel.configureBlocking(false);

        DatagramConnector connector = new DatagramConnector(datagramChannel,
                null);
        if (framerFactory != null) {
            connector.setFramerFactory(framerFactory);
        }
        if (listener != null) {
            connector.addListener(listener);
        }
        dispatcher = new Dispatcher();
        dispatcher.addChannelToRegister(new ChannelInterestOps(datagramChannel,
                SelectionKey.OP_READ, connector));
    }

    private void closeChannel() {
        try {
            datagramChannel.close();
        } catch (IOException e) {
        }
    }

    public SocketAddress getListenEndpoint() {
        return listenEndpoint;
    }

    public void start(String name) {
        try {
            openChannel();
        } catch (IOException e) {
        }
        dispatcher.start("datagram dispatcher");
        super.start("datagram acceptor");
    }

    public void stop() {
        synchronized (this) {
            notifyAll();
        }
        dispatcher.stop();
        closeChannel();
        super.stop();
    }

    public void run() {
        try {
            synchronized (this) {
                wait();
            }
        } catch (InterruptedException e) {
        }
    }

    public void setConnectionListener(ConnectionListener listener) {
        this.listener = listener;
    }

    public void setFramerFactory(IFramerFactory framerFactory) {
        this.framerFactory = framerFactory;
    }

}
